package com.CST.service.impl.zx;

import cn.hutool.core.date.DatePattern;
import com.CST.common.constant.Constants;
import com.CST.dto.zx.DeptBalanceDetailDTO;
import com.CST.dto.zx.EndingBalanceDTO;
import com.CST.dto.zx.PrimusCashDTO;
import com.CST.dto.zx.ZxDeptDirectorFundDTO;
import com.CST.entity.zx.ZX_PrimusCash;
import com.CST.entity.zx.ZxDeptDirectorFund;
import com.CST.entity.zx.ZxEtlAccountInfo;
import com.CST.mapper.cst.zx.ZxDeptDirectorFundMapper;
import com.CST.mapper.cst.zx.ZxSumMoneyMapper;
import com.CST.mapper.ufdata.AccvouchMapper;
import com.CST.service.zx.ZxDeptDirectorFundService;
import com.CST.util.ExcelTransfer;
import com.CST.util.HttpUtil;
import com.CST.vo.zx.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.CST.common.method.CommonMethod.getFirstDay;
import static com.CST.common.method.CommonMethod.getLastDay;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xnd
 * @since 2023-05-05
 */
@Service
@Slf4j
public class ZxDeptDirectorFundServiceImpl extends ServiceImpl<ZxDeptDirectorFundMapper, ZxDeptDirectorFund> implements ZxDeptDirectorFundService {
    @Autowired
    ZxSumMoneyMapper zxSumMoneyMapper;

    @Autowired
    AccvouchMapper accvouchMapper;

    @Autowired
    private ZxDeptDirectorFundMapper zxDeptDirectorFundMapper;

    @Autowired
    private ExcelTransfer<EndingBalanceVO> excelTransfer1;

    @Autowired
    private ExcelTransfer<DeptBalanceDetailVO> excelTransferE;

    @Autowired
    private ExcelTransfer<EndingBalanceDeptVO> excelTransferDept;

    @Override
    @Transactional
    public String gatherDeptDirectorInfo(ZxDeptDirectorFundDTO dto) {
        int year = dto.getDateTime().getYear();
        int month = dto.getDateTime().getMonthValue();
        LocalDate startDate = getFirstDay(year, month);//选择月的第一天
        LocalDate endDate = getLastDay(year, month);
        LocalDate lastMonthDate = startDate.minusDays(1);
        endDate = endDate.plusDays(1);//选择月下个月的第一天
        List<String> listSplit = Arrays.asList(startDate.toString().split("-"));
        List<String> lastMonthDateSplit = Arrays.asList(lastMonthDate.toString().split("-"));
        String period = listSplit.get(0) + listSplit.get(1);
        String lastPeriod = lastMonthDateSplit.get(0) + lastMonthDateSplit.get(1);
        //日期从2019年1月开始采集
        if (!"201901".equals(period)) {
            //获取选择年月的期初,期末记录
            LambdaQueryWrapper<ZxDeptDirectorFund> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ZxDeptDirectorFund::getPeriod,lastPeriod);
            List<ZxDeptDirectorFund> isExistList = list(lambdaQueryWrapper);
            if (isExistList.isEmpty()) {
                return "请先采集上月数据";
            }
        }
        log.info("{}", "进入用友采集环节》》》》》》》》》》》》");
        //从用友获取选择月的所有凭证
        List<ZxDeptDirectorFund> zxDeptDirectorFunds = accvouchMapper.gatherDeptDirectorInfo(year,
                startDate,
                endDate,
                period);
        //先删后插
        zxDeptDirectorFundMapper.deleteZxDeptDirectorFundByperiod(period);
        int fromIndex = 0;
        List<ZxDeptDirectorFund> insertList = new ArrayList<>();
        for (ZxDeptDirectorFund item : zxDeptDirectorFunds) {
            fromIndex++;
            insertList.add(item);
            if (fromIndex % 20 == 0 && fromIndex <= zxDeptDirectorFunds.size()) {
                saveBatch(insertList);
                insertList = new ArrayList<>();
            }
        }
        if (CollectionUtils.isNotEmpty(insertList)) {
            saveBatch(insertList);
        }
        return "success";
    }

    @Override
    public List<EndingBalanceVO> listDeptDirectorFundBalance(EndingBalanceDTO dto) {
        var dispose = new DeptBalanceDetailDTO();
        dispose.setDateTimeStart(dto.getDateTimeStart());
        dispose.setDateTimeEnd(dto.getDateTimeEnd());
        dispose.setDeptCode(dto.getDeptCode());
        //结束时间前一个月的第一天
        EndingBalanceDTO dispose1 = dispose(dto);
        //当前分页查询的
        String userId = HttpUtil.getRequestHeaderInfo(Constants.USER_ID);
        return zxDeptDirectorFundMapper.listDeptDirectorFundBalance(dispose1,
                userId);
    }

    @Override
    public List<DeptBalanceDetailVO> DeptDirectorFundBalanceByCode(DeptBalanceDetailDTO dto) {
        //当前页面用户想查询的年月范围 md&mc
        DeptBalanceDetailDTO atDto = disposeDetail(dto);
       //计算过程
        return countingProcess(atDto);
    }

    @Override
    public List<AllDeptVO> listDept() {
//        根据配置的科室权限获取列表
        String userId = HttpUtil.getRequestHeaderInfo("userId");
        return zxDeptDirectorFundMapper.listDept(userId);
    }

    @Override
    public List<PrimusCashVO> listPrimusCash(PrimusCashDTO entity) {
        return zxDeptDirectorFundMapper.listPrimusCash(entity);
    }

    @Override
    public void download(HttpServletResponse response, EndingBalanceDTO dto) throws IOException {
        List<EndingBalanceVO> endingBalanceVOS = listDeptDirectorFundBalance(dto);
        excelTransfer1.exportExcel(response, endingBalanceVOS, "科主任基金汇总", "sheet", EndingBalanceVO.class);
    }

    @Override
    public void downloadDept(HttpServletResponse response, EndingBalanceDTO dto) throws IOException {
        List<EndingBalanceVO> endingBalanceVOS = listDeptDirectorFundBalance(dto);
        List<EndingBalanceDeptVO> endingBalanceDeptVOS =new ArrayList<>();
        endingBalanceVOS.forEach(item->{
            EndingBalanceDeptVO info =new EndingBalanceDeptVO();
            BeanUtils.copyProperties(item,info);
            endingBalanceDeptVOS.add(info);
        });
        excelTransferDept.exportExcel(response, endingBalanceDeptVOS, "科主任基金汇总", "sheet", EndingBalanceDeptVO.class);
    }

    @Override
    public void downloadE(HttpServletResponse response, DeptBalanceDetailDTO dto) throws IOException {
        List<DeptBalanceDetailVO> deptBalanceDetailVOS = DeptDirectorFundBalanceByCode(dto);
        excelTransferE.exportExcel(response,
                deptBalanceDetailVOS,
                "科主任基金明细汇总",
                "sheet",
                DeptBalanceDetailVO.class);
    }

    @Override
    public Boolean saveOrUpdate(ZX_PrimusCash entity) {
        if(entity.getId()!=null && entity.getId()!=0)
        {
            //编辑
            zxDeptDirectorFundMapper.updatePrimusCash(entity);
        }
        else {
            //新增
            zxDeptDirectorFundMapper.insertPrimusCash(entity);
        }
        return true;
    }

    @Override
    public Boolean deletePrimusCash(Integer id) {
        return zxDeptDirectorFundMapper.deletePrimusCash(id);
    }

    @Override
    public Page<PrimusCashVO> xnsns(String year) {

        return zxDeptDirectorFundMapper.xnsnfas(new Page<PrimusCashVO>(1,20),year);
    }

    public DeptBalanceDetailDTO disposeDetail(DeptBalanceDetailDTO dto) {
        DeptBalanceDetailDTO deptBalanceDetailDTO = new DeptBalanceDetailDTO();
        //转换成LocalDate
        var DateTimeEnd = LocalDate.parse(dto.getDateTimeEnd(),
                DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
        //获取下个月第一天
        var nextTimeEnd = DateTimeEnd.with(TemporalAdjusters.firstDayOfNextMonth());
        log.info("下月输出{}", nextTimeEnd);
        //转换成String
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        var endTime = nextTimeEnd.format(formatter);
        BeanUtils.copyProperties(dto, deptBalanceDetailDTO);
        deptBalanceDetailDTO.setDateTimeEnd(endTime);
        return deptBalanceDetailDTO;
    }

    /**
     * 结束时间获取当前月下个月第一天
     * @param dto
     * @return
     */
    public EndingBalanceDTO dispose(EndingBalanceDTO dto) {
        EndingBalanceDTO endingBalanceDTO = new EndingBalanceDTO();
        //结束时间转换成LocalDate
        var DateTimeEnd = LocalDate.parse(dto.getDateTimeEnd(),
                DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
        //获取下个月第一天
        var nextTimeEnd = DateTimeEnd.with(TemporalAdjusters.firstDayOfNextMonth());
        //转换成String
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        var endTime = nextTimeEnd.format(formatter);
        endingBalanceDTO.setDateTimeStart(dto.getDateTimeStart());
        endingBalanceDTO.setDateTimeEnd(endTime);
        endingBalanceDTO.setDeptCode(dto.getDeptCode());
        endingBalanceDTO.setSort(dto.getSort());
        return endingBalanceDTO;
    }

    /**
     * 科主任基金明细逻辑处理弫
     * @param atDto
     * @return List<DeptBalanceDetailVO>集合
     */
    public List<DeptBalanceDetailVO> countingProcess(DeptBalanceDetailDTO atDto) {
        DeptBalanceDetailVO deptBalanceDetailVO = new DeptBalanceDetailVO();
        deptBalanceDetailVO.setDescription("总计");
        BigDecimal atmc = new BigDecimal("0");
        BigDecimal atmd = new BigDecimal("0");
        List<DeptBalanceDetailVO> currentData =
                zxDeptDirectorFundMapper.DeptDirectorFundBalanceByCode(atDto.getDeptCode(),
                atDto.getDateTimeStart(),
                atDto.getDateTimeEnd());
        if (!currentData.isEmpty()) {
            //mc贷方金额
            atmc = currentData.stream().map(DeptBalanceDetailVO::getMc).reduce(BigDecimal.ZERO, BigDecimal::add);
            //md借方金额
            atmd = currentData.stream().map(DeptBalanceDetailVO::getMd).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        deptBalanceDetailVO.setMc(atmc);
        deptBalanceDetailVO.setMd(atmd);
        currentData.add(deptBalanceDetailVO);
        return currentData;
    }
}
